package com.lening.common.base;

import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lening.common.enums.StatusEnum;
import com.lening.common.properties.TenantProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @author 牛强
 * @datetime 2024/4/15 10:09
 * @description 类对象
 */
@Slf4j
public class BaseServiceImpl<M extends BaseMapper<P>, P, D> extends ServiceImpl<M, P> implements BaseService<P, D> {
    @Resource
    private TenantProperties properties;


    /**
     * 新增
     */
    @Override
    public String add(P p) {
        return this.save(p) ? "新增成功" : "新增失败";
    }

    /**
     * 批量新增
     */
    @Override
    @Transactional
    public String adds(Collection<P> ps) {
        return this.saveBatch(ps,Integer.MAX_VALUE) ? "新增成功" : "新增失败";
    }

    /**
     * 修改
     */
    @Override
    public String update(P p) {
        return this.updateById(p) ? "修改成功" : "修改失败";
    }

    /**
     * 批量修改
     */
    @Override
    @Transactional
    public String updates(Collection<P> ps) {
        return this.updateBatchById(ps) ? "修改成功" : "修改失败";
    }

    /**
     * 新增或修改
     */
    @Override
    @Transactional
    public String addOrUpdate(P p) {
        String type = "修改";
        //1.判断是新增还是修改
        try {
            Method idMethod = p.getClass().getDeclaredMethod("getId");
            Object idValue = idMethod.invoke(p, new Object[]{});
            if (idValue == null) {
                type = "新增";
            }
        } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException |
                InvocationTargetException e) {
            log.error("addOrUpdate.message:{}", e.getMessage());
        }

        return this.saveOrUpdate(p) ? type + "成功" : type + "失败";
    }

    private String getIdMethodName(P p) {
        Field[] declaredFields = p.getClass().getDeclaredFields();
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            TableId annotation = declaredField.getAnnotation(TableId.class);
            if (annotation != null) {
                String idField = declaredField.getName();
                return "get" + idField.substring(0, 1).toUpperCase() + idField.substring(1);


            }
        }
        return null;
    }
    /**
     * 删除指定ID的数据
     */
    @Override
    public String delById(Long id) {
        return this.removeById(id) ? "删除成功" : "删除失败";
    }

    /**
     * 批量删除
     */
    @Override
    @Transactional
    public String delByIds(Collection<Long> ids) {
        return this.removeBatchByIds(ids) ? "删除成功" : "删除失败";
    }

    /**
     * 根据ID查询
     */
    @Override
    public P getById(Long id) {
        return this.baseMapper.selectById(id);
    }

    /**
     * 根据ID查询
     */
    @Override
    public List<P> getByIds(Collection<Long> ids) {
        return this.baseMapper.selectBatchIds(ids);
    }

    /**
     * 条件查询
     */
    @Override
    public List<?> list(D d) {
        QueryWrapper<P> wrapper = this.getLikeWrapper(d);
        return this.list(wrapper);
    }

    /**
     * 分页条件查询
     */
    @Override
    public Page<?> page(D d) {
        long current = 0, size = 0;
        try {
            //1.通过反射获取分页方法
            Method getCurrentMethod = d.getClass().getSuperclass().getMethod("getCurrent");
            Method getSizeMethod = d.getClass().getSuperclass().getMethod("getSize");

            //2.获取分页数据
            Object currentValue = getCurrentMethod.invoke(d, new Object[]{});
            Object sizeValue = getSizeMethod.invoke(d, new Object[]{});
            if (currentValue != null) {
                current = NumberUtil.parseLong(currentValue.toString());
            }
            if (sizeValue != null) {
                size = NumberUtil.parseLong(sizeValue.toString());
            }
        } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException |
                InvocationTargetException e) {
            log.error("page.message:{}", e.getMessage());
        }

        //1.分页数据
        Page<P> page = new Page<>(current, size);

        QueryWrapper<P> wrapper = this.getLikeWrapper(d);

        return this.baseMapper.selectPage(page, wrapper);
    }

    /**
     * 获取模糊查询条件
     */
    private QueryWrapper<P> getLikeWrapper(D d) {
        QueryWrapper<P> wrapper = new QueryWrapper<>();

        //2.获取DTO类对象的所有属性
        Field[] fields = d.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            String fieldName = field.getName();
            //name -> getName
            //age -> getAge
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getMethod = "get" + firstLetter + fieldName.substring(1);//getHeaderUrl

            //通过反射调用 getter方法
            Method declaredMethod = null;
            try {
                declaredMethod = d.getClass().getDeclaredMethod(getMethod);
                Object value = declaredMethod.invoke(d, new Object[]{});

                //获取属性名中大写字母的列表
                ArrayList<String> upList = countUppercase(fieldName);
                if (upList.size()>0) {
                    for (String s : upList) {
                        //将属性名中大写字母替换成“_小写字母”
                        fieldName=fieldName.replace(s, "_"+ s.toLowerCase());
                    }
                }
                if (properties.getLikeColumn().stream().anyMatch(fieldName::equals)) {
                    wrapper.like(value != null, fieldName, value);
                } else {
                    wrapper.eq(value != null, fieldName, value);
                }
            } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException |
                    InvocationTargetException e) {
                log.error("page.message:{}", e.getMessage());
            }
        }
        return wrapper;
    }

    private static ArrayList<String> countUppercase(String str) {
        ArrayList<String> upList = new ArrayList<>();
        char[] chars = str.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (Character.isUpperCase(chars[i])) {
                upList.add(chars[i] + "");
            }
        }
        return upList;
    }
    /**
     * 获取==条件
     */
    private QueryWrapper<P> getEqWrapper(D d) {
        QueryWrapper<P> wrapper = new QueryWrapper<>();

        //2.获取DTO类对象的所有属性
        Field[] fields = d.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            String fieldName = field.getName();
            //name -> getName
            //age -> getAge
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getMethod = "get" + firstLetter + fieldName.substring(1);

            //通过反射调用 getter方法
            Method declaredMethod = null;
            try {
                declaredMethod = d.getClass().getDeclaredMethod(getMethod);
                Object value = declaredMethod.invoke(d, new Object[]{});
                wrapper.eq(value != null, fieldName, value);
            } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException |
                    InvocationTargetException e) {
                log.error("page.message:{}", e.getMessage());
            }
        }
        return wrapper;
    }

    /**
     * 启用
     * @param id
     * @return
     */
    @Override
    public String enable(Long id) {
        boolean update = this.update().set("status", 1).eq("id", id).update();
        return update ? "启用成功" : "启用失败";
    }

    /**
     * 停用
     * @param id
     * @return
     */
    @Override
    public String unable(Long id) {
        boolean update = this.update().set("status", 0).eq("id", id).update();
        return update ? "停用成功" : "停用失败";
    }

    @Override
    public String verify(Long id) {
        boolean update = this.update().set(StatusEnum.Verify.getColumn(), StatusEnum.Verify.getValue()).eq("id", id).update();
        return update ? "验证失败" : "验证成功";
    }
    @Override
    public String unverify(Long id) {
        boolean update = this.update().set(StatusEnum.unVerify.getColumn(), StatusEnum.unVerify.getValue()).eq("id", id).update();
        return update ? "验证成功" : "验证失败";
    }
}
